﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using VideoStream.Model;

namespace VideoStream.CustomControl
{
    public partial class TVSlider : UserControl
    {
        public delegate void ValueChangedHandler(double value);

        private double value = 0;
        private Size barSize = new Size(5, 80);
        private Size handlerSize = new Size(15, 10);
        private Color barForeColor = TVColor.Color_HighLight;
        private Color barBackColor = TVColor.Color_WhiteDark;
        private Color handlerColor = TVColor.Color_HighLight;
        private Color handlerHoverColor = TVColor.Color_HighLightHover;
        private Color handlerPressColor = TVColor.Color_HighLightPress;
        private Orientation orientation = Orientation.Vertical;

        public Size BarSize
        {
            get { return barSize; }
            set
            {
                barSize = value;
                UpdateBarSize();
                UpdateHandlerLocation();
                UpdateBarHeight();
            }
        }
        public Size HandlerSize
        {
            get { return handlerSize; }
            set
            {
                handlerSize = value;
                handler.Size = HandlerSize;
                UpdateHandlerLocation();
            }
        }

        public double Value
        {
            get
            {
                return value;
            }
            set
            {
                double tmp = Math.Max(Math.Min(value, 100), 0);
                if (tmp != this.value)
                {
                    this.value = tmp;
                    UpdateHandlerLocation();
                    UpdateBarHeight();
                    ValueChanged?.Invoke(Value);
                }
            }
        }

        public Color BarForeColor
        {
            get { return barForeColor; }
            set
            {
                barForeColor = value;
                bar.BackColor = BarForeColor;
            }
        }
        public Color BarBackColor
        {
            get { return barBackColor; }
            set
            {
                barBackColor = value;
                barbg.BackColor = BarBackColor;
            }
        }
        public Color HandlerColor
        {
            get { return handlerColor; }
            set
            {
                handlerColor = value;
                handler.BackColor = HandlerColor;
            }
        }
        public Color HandlerHoverColor
        {
            get { return handlerHoverColor; }
            set
            { handlerHoverColor = value; }
        }
        public Color HandlerPressColor
        {
            get { return handlerPressColor; }
            set
            {

                handlerPressColor = value;
            }
        }
        public Cursor _Cursor
        {
            get { return handler.Cursor; }
            set { handler.Cursor = value; }
        }
        public event EventHandler CMouseEnter
        {
            add
            {
                handler.MouseEnter += value;
                bar.MouseEnter += value;
                barbg.MouseEnter += value;
                this.MouseEnter += value;
            }
            remove
            {
                handler.MouseEnter -= value;
                bar.MouseEnter -= value;
                barbg.MouseEnter -= value;
                this.MouseEnter -= value;
            }
        }

        public event EventHandler CMouseLeave
        {
            add
            {
                handler.MouseLeave += value;
                bar.MouseLeave += value;
                barbg.MouseLeave += value;
                this.MouseLeave += value;
            }
            remove
            {
                handler.MouseLeave -= value;
                bar.MouseLeave -= value;
                barbg.MouseLeave -= value;
                this.MouseLeave -= value;
            }
        }

        public Orientation Orientation
        {
            get { return orientation; }
            set
            {
                orientation = value;
                UpdateBarSize();
                UpdateHandlerLocation();
                UpdateBarHeight();
                switch (Orientation)
                {
                    case Orientation.Horizontal:
                        bar.Dock = DockStyle.Left;
                        break;
                    case Orientation.Vertical:
                        bar.Dock = DockStyle.Bottom;
                        break;
                    default:
                        break;
                }
            }
        }


        private Padding newPadd = Padding.Empty;
        private Point newPoint = Point.Empty;
        private Size barForeSize = Size.Empty;
        private bool isPressed = false;

        public event ValueChangedHandler ValueChanged;

        public TVSlider()
        {
            InitializeComponent();

            SizeChanged += TVSlider_SizeChanged;
            handler.MouseDown += Handler_MouseDown;
            handler.MouseMove += Handler_MouseMove;
            handler.MouseUp += Handler_MouseUp;

            bar.MouseDown += Bar_MouseDown;
            barbg.MouseDown += Barbg_MouseDown;
        }

        private void Barbg_MouseDown(object sender, MouseEventArgs e)
        {
            switch (Orientation)
            {
                case Orientation.Horizontal:
                    Value = (1 - (double)e.X / (double)BarSize.Width) * 100;
                    break;
                case Orientation.Vertical:
                    Value = (1 - (double)e.Y / (double)BarSize.Height) * 100;
                    break;
                default:
                    break;
            }
        }

        private void Bar_MouseDown(object sender, MouseEventArgs e)
        {
            switch (Orientation)
            {
                case Orientation.Horizontal:
                    Value = (1 - (double)(e.X + bar.Top) / (double)BarSize.Width) * 100;
                    break;
                case Orientation.Vertical:
                    Value = (1 - (double)(e.Y + bar.Top) / (double)BarSize.Height) * 100;
                    break;
                default:
                    break;
            }

        }

        private void CtlMouseLeave(object sender, EventArgs e)
        {
            this.OnMouseEnter(e);
        }

        private void CtlMouseEnter(object sender, EventArgs e)
        {
            this.OnMouseLeave(e);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics;
            Pen p = new Pen(TVColor.Color_HighLight, 1);
            g.DrawRectangle(p, 0, 0, this.Width - p.Width, this.Height - p.Width);
        }

        private void Handler_MouseUp(object sender, MouseEventArgs e)
        {
            isPressed = false;
            this.OnMouseUp(e);
        }

        private void Handler_MouseMove(object sender, MouseEventArgs e)
        {
            if (isPressed)
            {

                switch (Orientation)
                {
                    case Orientation.Horizontal:
                        Value -= (double)e.X / (BarSize.Width) * 100;
                        break;
                    case Orientation.Vertical:
                        Value -= (double)e.Y / (BarSize.Height) * 100;
                        break;
                    default:
                        break;
                }

            }

            this.OnMouseMove(e);
        }

        private void Handler_MouseDown(object sender, MouseEventArgs e)
        {
            isPressed = true;
            this.OnMouseDown(e);
        }

        private void TVSlider_SizeChanged(object sender, EventArgs e)
        {
            UpdateBarSize();
            UpdateHandlerLocation();
            UpdateBarHeight();
        }

        private void UpdateBarSize()
        {
            //switch (Orientation)
            //{
            //    case Orientation.Horizontal:
            //        int paddT = (this.Width - BarSize.Width) / 2;
            //        int paddB = (this.Height - BarSize.Height) / 2;
            //        newPadd.Top = newPadd.Right = paddH;
            //        newPadd.Bottom = newPadd.Bottom = paddV;
            //        this.Padding = newPadd;
            //        break;
            //    case Orientation.Vertical:
            //        int paddH = (this.Width - BarSize.Width) / 2;
            //        int paddV = (this.Height - BarSize.Height) / 2;
            //        newPadd.Left = newPadd.Right = paddH;
            //        newPadd.Top = newPadd.Bottom = paddV;
            //        this.Padding = newPadd;
            //        break;
            //    default:
            //        break;
            //}

            int paddH = (this.Width - BarSize.Width) / 2;
            int paddV = (this.Height - BarSize.Height) / 2;
            newPadd.Left = newPadd.Right = paddH;
            newPadd.Top = newPadd.Bottom = paddV;
            this.Padding = newPadd;

        }

        private void UpdateHandlerLocation()
        {
            switch (Orientation)
            {
                case Orientation.Horizontal:
                    newPoint.Y = (this.Height - HandlerSize.Height) / 2;
                    newPoint.X = (int)(this.Padding.Left + BarSize.Width * (((100 - Value) / 100d)) - HandlerSize.Width / 2);
                    handler.Location = newPoint;
                    break;
                case Orientation.Vertical:
                    newPoint.Y = (int)(this.Padding.Top + BarSize.Height * (1 - (Value / 100d)) - HandlerSize.Height / 2);
                    newPoint.X = (this.Width - HandlerSize.Width) / 2;
                    handler.Location = newPoint;
                    break;
                default:
                    break;
            }

        }

        private void UpdateBarHeight()
        {
            double ps = Value / 100d;
            switch (Orientation)
            {
                case Orientation.Horizontal:
                    barForeSize.Height = BarSize.Height;
                    barForeSize.Width = (int)(BarSize.Width * (1 - ps));
                    bar.Size = barForeSize;
                    break;
                case Orientation.Vertical:
                    barForeSize.Width = BarSize.Width;
                    barForeSize.Height = (int)(BarSize.Height * ps);
                    bar.Size = barForeSize;
                    break;
                default:
                    break;
            }

        }
    }
}
public enum Orientation
{
    Horizontal,
    Vertical,
}
